﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Web;
using Sausage.Common;
using Sausage.Web.Code;
using Sausage.Web.DataModel;
using Sausage.Web.Models;
using Telerik.Web.Mvc;

namespace Sausage.Web.Domain
{
    public class MaintainLabourHelper
    {
        public static GridModel<object> Select(JosnPagingQueryModel query)
        {
            Guid targetID;
            var isWithChild = Helper.IsNeedOrganizationQuery(query, out targetID);
            List<Guid> organization = OrganizationHelper.GetAllowedOrganizationList(isWithChild, targetID); 
            using (var context = new SausageEntities())
            {
                return
                    QueryMaintainLabour
                    (
                        context.MaintainLabour.Where
                        (
                            item =>
                             organization.Contains(item.OrganizationID) &&
                             item.State == (int)MaintainDataStateEnum.Confirmed),
                        query, isWithChild);
            }
        }

        public static GridModel<object> SubmitSelect(JosnPagingQueryModel query)
        {
            Guid targetID;
            var isWithChild = Helper.IsNeedOrganizationQuery(query, out targetID);
            List<Guid> organization = OrganizationHelper.GetAllowedOrganizationList(isWithChild, targetID);
            using (var context = new SausageEntities())
            {
                return
                    QueryMaintainLabour(
                        context.MaintainLabour.Where(
                            item =>
                            organization.Contains(item.OrganizationID) &&
                            (item.State == (int)MaintainDataStateEnum.Unsubmit ||
                             item.State == (int)MaintainDataStateEnum.AuditRejected)),
                        query, isWithChild);
            }
        }

        public static GridModel<object> AuditSelect(JosnPagingQueryModel query)
        {
            Guid targetID;
            var isWithChild = Helper.IsNeedOrganizationQuery(query, out targetID);
            List<Guid> organization = OrganizationHelper.GetAllowedOrganizationList(isWithChild, targetID);
            using (var context = new SausageEntities())
            {
                return
                    QueryMaintainLabour(context.MaintainLabour.Where(item =>
                    organization.Contains(item.OrganizationID) &&
                    (item.State == (int)MaintainDataStateEnum.Submitted ||
                     item.State == (int)MaintainDataStateEnum.ConfirmationRejected))
                    , query, isWithChild);
            }
        }

        public static GridModel<object> ConfirmSelect(JosnPagingQueryModel query)
        {
            Guid targetID;
            var isWithChild = Helper.IsNeedOrganizationQuery(query, out targetID);
            List<Guid> organization = OrganizationHelper.GetAllowedOrganizationList(isWithChild, targetID);
            using (var context = new SausageEntities())
            {
                return
                    QueryMaintainLabour(context.MaintainLabour.Where(item =>
                    organization.Contains(item.OrganizationID) && item.State == (int)MaintainDataStateEnum.Audited)
                    , query, isWithChild);
            }
        }

        private static GridModel<object> QueryMaintainLabour(IQueryable<MaintainLabour> source, JosnPagingQueryModel query, bool isWithChild)
        {
            var result = UIHelper.GetGridModelFromQueryModel<MaintainLabour>(
                source,
                query.page,
                query.limit,
                GetSortDescriptorFromQueryModel(query.SortModel),
                GetSearchFilterFromQueryModel(query.FilterModel, isWithChild));

            var list = result.Data.Select(maintainLabour => new
                                                                {
                                                                    LabourID = maintainLabour.LabourID,
                                                                    QuantityID = maintainLabour.QuantityID,
                                                                    OrganizationID = maintainLabour.OrganizationID,
                                                                    Organization = maintainLabour.Organization.OrganizationName,
                                                                    JobID = maintainLabour.JobID,
                                                                    Job = maintainLabour.Job.ItemName,
                                                                    LabourTypeID = maintainLabour.LabourTypeID,
                                                                    LabourType = maintainLabour.LabourType.ItemName,
                                                                    MaintainCode = maintainLabour.MaintainQuantity.MaintainCode,
                                                                    Quantity = maintainLabour.Quantity,
                                                                    Price = maintainLabour.Price,
                                                                    Amount = maintainLabour.Amount,
                                                                    CreateDate = maintainLabour.CreateDate,
                                                                    Applicant = maintainLabour.Applicant,
                                                                    ApplicationDate = maintainLabour.ApplicationDate,
                                                                    Auditor = maintainLabour.Auditor,
                                                                    AuditedDate = maintainLabour.AuditedDate,
                                                                    Approver = maintainLabour.Approver,
                                                                    ApprovedDate = maintainLabour.ApprovedDate,
                                                                    State = maintainLabour.State,
                                                                    IsDelay = maintainLabour.IsDelay,
                                                                    Memo = maintainLabour.Memo,
                                                                    maintainLabour.Comment
                                                                }).ToList();
            return new GridModel<object>()
            {
                Aggregates = result.Aggregates,
                Data = list,
                Total = result.Total
            };
        }

        private static List<IFilterDescriptor> GetSearchFilterFromQueryModel(IEnumerable<JosnQueryFilterModel> filterModels, bool isWithChild)
        {
            var filterList = new List<IFilterDescriptor>();
            foreach (var item in filterModels)
            {
                if (string.IsNullOrEmpty(item.value))
                    continue;

                if (item.property == "OrganizationID" && isWithChild)
                    continue;

                if (item.property.EndsWith("ID", StringComparison.InvariantCultureIgnoreCase))
                {
                    var targetID = Guid.Parse(item.value);
                    if (targetID != Guid.Empty)
                        filterList.Add(new FilterDescriptor(item.property, FilterOperator.IsEqualTo, targetID));
                }
                else if (item.property == "ApplicationDate_L") //startData - begin
                {
                    var targetDate = DateTime.Parse(item.value);
                    filterList.Add(new FilterDescriptor("ApplicationDate", FilterOperator.IsGreaterThanOrEqualTo, targetDate));
                }
                else if (item.property == "ApplicationDate_H") // startDate - end.
                {
                    var targetDate = DateTime.Parse(item.value);
                    filterList.Add(new FilterDescriptor("ApplicationDate", FilterOperator.IsLessThanOrEqualTo, targetDate));
                }
                else //other filter.
                    filterList.Add(new FilterDescriptor(item.property, FilterOperator.Contains, item.value));
            }
            return filterList;
        }

        private static List<SortDescriptor> GetSortDescriptorFromQueryModel(IEnumerable<JosnQuerySortModel> sortModels)
        {
            //convert the sort description.
            var sortList = new List<SortDescriptor>();
            foreach (var item in sortModels)
            {
                var descriptor = new SortDescriptor()
                {
                    Member = item.property,
                    SortDirection =
                        item.direction.ToLower() == "desc"
                            ? ListSortDirection.Descending
                            : ListSortDirection.Ascending
                };

                if (descriptor.Member == "Organization")
                    descriptor.Member = "Organization.OrganizationName";
                else if (descriptor.Member == "MaintainCode")
                    descriptor.Member = "MaintainQuantity.MaintainCode";
                else if (descriptor.Member == "Job")
                    descriptor.Member = "Job.ItemName";
                else if (descriptor.Member == "LabourType")
                    descriptor.Member = "LabourType.ItemName";
                sortList.Add(descriptor);
            }
            return sortList;

        }

        public static void DeleteMaintainLabour(Guid id)
        {
            using (var context = new SausageEntities())
            {
                var maintainLabour = new MaintainLabour();
                maintainLabour.LabourID = id;

                context.CreateObjectSet<MaintainLabour>().Attach(maintainLabour);
                context.ObjectStateManager.ChangeObjectState(maintainLabour, EntityState.Deleted);
                context.SaveChanges();
            }
        }

        public static MaintainLabour GetMaintainLabourByID(Guid id)
        {
            using (var context = new SausageEntities())
            {
                return
                    context.MaintainLabour.Include("Organization").Include("Job").Include("LabourType").Include("MaintainQuantity").FirstOrDefault(
                        maintainLabour => maintainLabour.LabourID == id);
            }
        }

        public static void UpdateMaintainLabour(MaintainLabourListRow data)
        {
            using (var context = new SausageEntities())
            {
                var maintainLabour = context.MaintainLabour.FirstOrDefault(item => item.LabourID == data.LabourID);
                if (maintainLabour == null)
                    return;

                if (maintainLabour.State != (int)MaintainDataStateEnum.Unsubmit && maintainLabour.State != (int)MaintainDataStateEnum.AuditRejected)
                    throw new SausageException(string.Format("养护人工已经提交，不允许执行编辑操作。"));


                maintainLabour.QuantityID = data.QuantityID;
                maintainLabour.JobID = data.JobID;
                maintainLabour.LabourTypeID = data.LabourTypeID;
                maintainLabour.Price = data.Price;
                maintainLabour.Amount = data.Price * data.Quantity;
                maintainLabour.Quantity = data.Quantity;
                maintainLabour.Applicant = Helper.CurrentPrincipal.User.UserName;
                //maintainLabour.ApplicationDate = data.ApplicationDate;
                maintainLabour.Memo = data.Memo;

                context.SaveChanges();
            }
        }

        public static void UpdateMaintainLabourState(Guid id, int state)
        {
            using (var context = new SausageEntities())
            {
                var maintainLabour = context.MaintainLabour.FirstOrDefault(item => item.LabourID == id);
                if (maintainLabour == null)
                    return;

                maintainLabour.State = state;
                context.SaveChanges();
            }
        }

        public static void CreateMaintainLabour(MaintainLabourListRow data)
        {
            using (var context = new SausageEntities())
            {
                MaintainLabour entity = new MaintainLabour();

                entity.LabourID = Guid.NewGuid();
                entity.QuantityID = data.QuantityID;
                entity.OrganizationID = Helper.CurrentPrincipal.Organization.OrganizationID;
                entity.JobID = data.JobID;
                entity.LabourTypeID = data.LabourTypeID;
                entity.Quantity = data.Quantity;
                entity.Price = data.Price;
                entity.Amount = data.Price * data.Quantity;
                entity.CreateDate = DateTime.Now;
                entity.Applicant = Helper.CurrentPrincipal.User.UserName;
                entity.ApplicationDate = data.ApplicationDate;
                entity.State = (int)MaintainDataStateEnum.Unsubmit;

                entity.IsDelay = Helper.IsDelay(data.ApplicationDate);
                entity.Memo = data.Memo;

                context.AddToMaintainLabour(entity);
                context.SaveChanges();
            }
        }

        public static void ExecuteSubmit(Guid[] labours)
        {
            if (null != labours && labours.Length > 0)
            {
                using (var context = new SausageEntities())
                {
                    var list = context.MaintainLabour.Where(item => labours.Contains(item.LabourID)).ToList();

                    foreach (var entity in list)
                    {
                        entity.State = (int)MaintainDataStateEnum.Submitted;
                    }
                    context.SaveChanges();
                }
            }
        }

        public static void ExecuteAudit(Guid[] labours,  bool passed,string comment)
        {
            if (null != labours && labours.Length > 0)
            {
                using (var context = new SausageEntities())
                {
                    var list = context.MaintainLabour.Where(item => labours.Contains(item.LabourID)).ToList();

                    foreach (var maintainLabour in list)
                    {
                        maintainLabour.Auditor = Helper.CurrentPrincipal.User.UserName;
                        maintainLabour.AuditedDate = DateTime.Now;
                        maintainLabour.Comment = comment;
                        maintainLabour.State = passed
                                                     ? (int)MaintainDataStateEnum.Audited
                                                     : (int)MaintainDataStateEnum.AuditRejected;
                    }
                    context.SaveChanges();
                }
            }
        }

        public static void ExecuteConfirm(Guid[] labours, bool passed, string comment)
        {
            if (null != labours && labours.Length > 0)
            {
                using (var context = new SausageEntities())
                {
                    var list = context.MaintainLabour.Where(item => labours.Contains(item.LabourID)).ToList();

                    foreach (var maintainLabour in list)
                    {
                        maintainLabour.Approver = Helper.CurrentPrincipal.User.UserName;
                        maintainLabour.ApprovedDate = DateTime.Now;
                        maintainLabour.Comment = comment;
                        maintainLabour.State = passed
                                                     ? (int)MaintainDataStateEnum.Confirmed
                                                     : (int)MaintainDataStateEnum.ConfirmationRejected;
                    }
                    context.SaveChanges();
                }
            }
        }
    }
}